#include "protect.h"

BMS_Protect_Typedef BMS_state;
BMS_Alert_flag_Typedef BMS_Alert_flag; 


//充电时：过流，过温，低温
//将采集到的电压，温度数据进行冒泡排序后和保护阈值进行比较
static void BMS_Charge_protect(void)
{
    static uint32_t ProtectCount=0;
    //过流
    if(BQ_SampleData.BatteryCurrent>OCC_Protect)
    {
        ProtectCount+=200;
        if(ProtectCount/60>=1)//充电过流延时为1s
        {
            BQ_ControlDSGOrCHG(CHG_CONTROL,BQ_STATE_DISABLE);//关闭充电开关
            xTimerStart(protect_timer_handle,portMAX_DELAY);
            BMS_Alert_flag=FlAG_ALERT_OCC;
            BMS_state=Protect_state_relieve_wait;      
            printf("OCC Tigger\r\n");
        }
    }//过温
    else if(deal_data.temp[4]>OTC_Protect_Temp)
    {
       BQ_ControlDSGOrCHG(CHG_CONTROL,BQ_STATE_DISABLE);//关闭充电开关
       BMS_Alert_flag=FlAG_ALERT_OTC;
       BMS_state=Protect_state_relieve_wait;
       printf("OTC Tigger\r\n");
    }//低温
    else if(deal_data.temp[0]<LTC_Protect_Temp)
    {
       BQ_ControlDSGOrCHG(CHG_CONTROL,BQ_STATE_DISABLE);//关闭充电开关
       BMS_Alert_flag=FlAG_ALERT_LTC;
       BMS_state=Protect_state_relieve_wait;
       printf("LTC Tigger\r\n");
    }
    else
    {
        ProtectCount=0;
    }
}

//放电监控，放电速率由电池决定，所以不做出判断
static void BMS_Discharge_protect(void)
{
    //过温
     if(deal_data.temp[4]>OTD_Protect_Temp)
     {
        BQ_ControlDSGOrCHG(DSG_CONTROL,BQ_STATE_DISABLE);//关闭放电开关
        BMS_Alert_flag=FlAG_ALERT_OTD;
        BMS_state=Protect_state_relieve_wait;
        printf("OTD Tigger\r\n");
         OLED_ShowChar(3,3,'w');
     }//低温
     else if(deal_data.temp[0]<LTD_Protect_Temp)
     {
       BQ_ControlDSGOrCHG(DSG_CONTROL,BQ_STATE_DISABLE);//关闭放电开关
       BMS_Alert_flag=FlAG_ALERT_LTD;
       BMS_state=Protect_state_relieve_wait;
       printf("LTD Tigger\r\n");
     }
}

//不同模式下执行不同监控函数
static void BMS_ProtectSwMonitor(void)
{
    switch(BMS_SYS_Mode.SYS_Mode)
    {
        case BMS_Mode_Charge:
        {
            BMS_Charge_protect();
        }break;
        
        case BMS_Mode_Discharge:
        {
            BMS_Discharge_protect();
        }break;
        default://睡眠和待机模式监控省略
            break;
    }
}
    
//不同模式下解除等待或监控恢复
static void BMS_ProtectRelieveWait(void)
{
    switch(BMS_Alert_flag)
    {
        case FlAG_ALERT_OV:
        {
            if(deal_data.Volt[4]<TLB_OV_RELIEVE)
            {
                BMS_state=Protect_state_relieve;
                printf("OV relieve\r\n");
            }
        }break;
        
        case FlAG_ALERT_UV:
        {
            if(deal_data.Volt[0]>TLB_UV_RELIEVE)
            {
                BMS_state=Protect_state_relieve;
                printf("UV relieve\r\n");
            }      
        }break;
          
        case FlAG_ALERT_OTC:
        {
            if(deal_data.temp[4]<OTC_Relieve_Temp)
            {
                BMS_state=Protect_state_relieve;
                printf("OTC relieve\r\n");
            }
        }break;
        
        case FlAG_ALERT_OTD:
        {
            if(deal_data.temp[4]<OTD_Relieve_Temp)
            {
                BMS_state=Protect_state_relieve;
                printf("OTD relieve\r\n");
            }
        }break;
        
        case FlAG_ALERT_LTC:
        {
            if(deal_data.temp[0]>LTC_Protect_Temp)
            {
                BMS_state=Protect_state_relieve;
                printf("LTC relieve\r\n");
            }
        }break;
        case FlAG_ALERT_LTD:
        {
            if(deal_data.temp[0]>LTD_Relieve_Temp)
            {
                BMS_state=Protect_state_relieve;
                printf("LTD relieve\r\n");
            }
        }break;
        default:
            break;
    }
}

//解除保护
static void BMS_ProtectRelieve(void)
{
    switch(BMS_Alert_flag)//这种写法程序不会卡住，会一直扫描，当检测到充电异常时执行充电控制函数，检测到放电异常时执行放电控制函数
    {
        case FlAG_ALERT_OCC:
		case FlAG_ALERT_OTC:
		case FlAG_ALERT_LTC:
            BQ_ControlDSGOrCHG(CHG_CONTROL,BQ_STATE_DISABLE);
        break;
        
        case FlAG_ALERT_OCD:
		case FlAG_ALERT_OTD:
		case FlAG_ALERT_LTD:
		case FlAG_ALERT_SCD:
            BQ_ControlDSGOrCHG(DSG_CONTROL,BQ_STATE_DISABLE);
        break;
        
        default:
            break;
    }
    
    BMS_Alert_flag=FlAG_ALERT_NO;
    BMS_state=Protect_state_monitor;
    printf("Protect Relieve\r\n");
    
}

//过流和过压需要硬件来保护
void BMS_ProtectHwMonitor(void)
{
    switch(BMS_Alert_flag)
    {
        case FlAG_ALERT_OCD:
		{
            xTimerStart(protect_timer_handle,portMAX_DELAY);//用定时器定时60s防止瞬间过流误保护
            BMS_state=Protect_state_relieve_wait;
            printf("OCD Tigger\r\n");
        }break;
        case FlAG_ALERT_SCD:
        {
            xTimerStart(protect_timer_handle,portMAX_DELAY);
            BMS_state=Protect_state_relieve_wait;
            printf("SCD Tigger\r\n");
        }break;
        case FlAG_ALERT_OV:
		{
            BMS_state=Protect_state_relieve_wait;
            printf("OV Tigger\r\n");
        }break;
        case FlAG_ALERT_UV:
		{
            BMS_state=Protect_state_relieve_wait;
            printf("UV Tigger\r\n");
            OLED_ShowChar(3,5,'w');
        }break;
        default:
            break;
    }
}


void protect_timer_Callback(TimerHandle_t xTimer)
{
    BMS_state=Protect_state_relieve;
    printf("Protect Timer Start");
}

void BMS_protect(void *pvParameters)
{
    for(;;)
    {
        
        switch(BMS_state)
        {
            case Protect_state_monitor:
            {
                BMS_ProtectHwMonitor();
                BMS_ProtectSwMonitor();
            }break;
            case Protect_state_relieve_wait:
            {
                BMS_ProtectRelieveWait();
            }break;
            case Protect_state_relieve:
            {
                BMS_ProtectRelieve();
            }break;
       } 
        osDelay(200);  
      }        
}


